#pragma once
#include <Rz/Object.h>
#include <Rz/Graphics/Math/Rectangle.h>
#include "CompositionAdapters/ICompositionAdapter.h"
#include "SceneVisitors/ISceneVisitor.h"
#include "IRenderDevice.h"
#include "GBuffer.h"

RZ_CLASS_FWD_DECL3(Rz, Graphics, Scene, CameraNode);

namespace Rz { namespace Graphics { namespace Render {

class Viewport :
	public Object,
	public IDeviceResource
{
	public:
		RZ_RTTI(Rz::Graphics::Render, Viewport);
		RZ_RTTI_IMPLEMENTS(Object, IDeviceResource);
		RZ_RTTI_END;

		Viewport(IRenderDevice* renderDevice, const Math::Rectangle& bounds);

		void Draw();

		const CompositionAdapters::ICompositionAdapter* GetCompositionAdapter() const;
		CompositionAdapters::ICompositionAdapter* GetCompositionAdapter() ;
		void SetCompositionAdapter(CompositionAdapters::ICompositionAdapter* compositionAdapter);

		const SceneVisitors::ISceneVisitor* GetSceneVisitor() const;
		SceneVisitors::ISceneVisitor* GetSceneVisitor();
		void SetSceneVisitor(SceneVisitors::ISceneVisitor* sceneVisitor);

		const Scene::CameraNode* GetCamera() const;
		Scene::CameraNode* GetCamera();
		void SetCamera(Scene::CameraNode* camera);

		Math::Size GetSize() const;
		void SetSize(const Math::Size& size);

		const Math::Rectangle& GetBounds() const;
		void SetBounds(const Math::Rectangle& bounds);

		f32 GetNear() const;
		void SetNear(f32 nearPlane);

		f32 GetFar() const;
		void SetFar(f32 farPlane);

		virtual Math::Vector3 Project(const Math::Vector3& source, const Math::Matrix4& projection, const Math::Matrix4& view, const Math::Matrix4& world) const;
		virtual Math::Vector3 Unproject(const Math::Vector3& source, const Math::Matrix4& projection, const Math::Matrix4& view, const Math::Matrix4& world) const;

	private:
		Math::Rectangle _bounds;
		f32 _near;
		f32 _far;

		Ptr<Scene::CameraNode> _cameraNode;
		Ptr<CompositionAdapters::ICompositionAdapter> _compositionAdapter;
		Ptr<SceneVisitors::ISceneVisitor> _sceneVisitor;
};

} } }
